package org.aspectsense.middleware.monitor;

import java.lang.annotation.Annotation;
import java.util.logging.Logger;

import org.aspectsense.middleware.annotations.Component;
import org.aspectsense.middleware.annotations.Service;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;

/**
 * Implements the OSGi <code>ServiceListener</code> for listening to service changes.<p>
 * Whenever a new <code>BundleEvent</code> is generated it overrides the
 * bundleChanged method to catch and manage received bundle event.
 */

	public class DefaultServiceListener implements ServiceListener
	{
	    private static final Logger logger = Logger.getLogger(DefaultServiceListener.class.getCanonicalName());

	    @Override
	    /**
	     * Overrides the OSGi <code>serviceChanged</code> method
	     * in order to catch and manages service events.
	     * @param serviceEvent The service monitored by OSGi
	     *
	     */
	    public void serviceChanged(ServiceEvent serviceEvent)
	    {
	        final int serviceEventType = serviceEvent.getType();

	        switch (serviceEventType)
	        {
	            case ServiceEvent.REGISTERED:
	                handleRegisteredService(serviceEvent.getServiceReference());
	                break;

	            case ServiceEvent.MODIFIED:
	                handleModifiedService(serviceEvent.getServiceReference());
	                break;

	            case ServiceEvent.UNREGISTERING:
	                handleUnregisteringService(serviceEvent.getServiceReference());
	                break;
	        }
	    }

	    private void handleRegisteredService(ServiceReference serviceReference)
	    {
	        logger.info("DefaultServiceListener::handleRegisteredService -> " + serviceReference.toString());

	        final Class<? extends Object> serviceProviderClass = getServiceProviderClass(serviceReference);
	        System.out.println("  serviceProviderClass -> " + serviceProviderClass);
	        final Component componentAnnotation = getComponentAnnotation(serviceProviderClass);
	        System.out.println("  componentAnnotation -> " + componentAnnotation);
	        final Service serviceAnnotation = getServiceAnnotation(serviceProviderClass, serviceReference);
	        System.out.println("  serviceAnnotation -> " + serviceAnnotation);
	    }
	    
	    /**
	     * Informs the Logger object about a service modification.
	     * @param serviceReference a reference to the modified service object.
	     */
	    private void handleModifiedService(ServiceReference serviceReference)
	    {
	        logger.info("DefaultServiceListener::handleModifiedService -> " + serviceReference.toString());
	    }
	    
	    /**
	     * Informs the Logger object about the unregistration of a service.
	     * @param serviceReference a reference to the unregistering service object.
	     */
	    private void handleUnregisteringService(ServiceReference serviceReference)
	    {
	        logger.info("DefaultServiceListener::handleUnregisteringService -> " + serviceReference.toString());
	    }

	    private Object getServiceProvider(final ServiceReference serviceReference)
	    {
	        final Bundle bundle = serviceReference.getBundle();
	        final BundleContext bundleContext = bundle.getBundleContext();
	        return bundleContext.getService(serviceReference);
	    }

	    private Class<? extends Object> getServiceProviderClass(final ServiceReference serviceReference)
	    {
	        return getServiceProvider(serviceReference).getClass();
	    }

	    private Component getComponentAnnotation(final Class<?> clazz)
	    {
	        final Annotation[] annotations = clazz.getDeclaredAnnotations();
	        System.out.println("    |annotations| = " + annotations.length);
	       
	        for(int i = 0; i < annotations.length; i++)
	        {
	            System.out.println(i + "\t" + annotations[i]);
	        }

	        return (Component) clazz.getAnnotation(Component.class);
	    }

	    private Service getServiceAnnotation(final Class<?> clazz, final ServiceReference serviceReference)
	    {
	        return null; // todo
	    }


}

